package runesim.shared;
/**
 * Library class to do text operations.
 * 
 * @author Ben
 */
public class Text {
	
	/**
	 * Converts a byte array to a string of hex values.
	 * 
	 * @param data
	 *            The data to convert.
	 * @return The String of hex.
	 */
	public static String dataToHex(byte[] data) {
		return dataToHex(data, 0, data.length);
	}
	
	/**
	 * Converts a byte array to a string of hex values.
	 * 
	 * @param data
	 *            The data to convert.
	 * @param offset
	 *            The offset to begin with.
	 * @param len
	 *            The length of the data to end on.
	 * @return The String of hex.
	 */
	public static String dataToHex(byte data[], int offset, int len) {
		String temp = "";
		for(int cntr = 0; cntr < len; cntr++) {
			int num = data[offset + cntr] & 0xFF;
			String myStr;
			if(num < 16)
				myStr = "0";
			else
				myStr = "";
			temp += myStr + Integer.toHexString(num) + " ";
		}
		return temp.toUpperCase().trim();
	}
	
	/**
	 * Converts a series of hex to an integer.
	 * 
	 * @param data
	 *            The data to convert.
	 * @param offset
	 *            The offset to begin with.
	 * @param len
	 *            The length of the data to end with.
	 * @return The converted integer.
	 */
	public static int hexToInt(byte data[], int offset, int len) {
		int temp = 0;
		int i = 1000;
		for(int cntr = 0; cntr < len; cntr++) {
			int num = (data[offset + cntr] & 0xFF) * i;
			temp += (int) num;
			if(i > 1)
				i = i / 1000;
		}
		return temp;
	}
	
	/**
	 * Converts a string to a long value. Used for player name storage.
	 * 
	 * @param s
	 *            The string to convert.
	 * @return The converted long value.
	 */
	public static long stringToLong(String s) {
		long hash = 0L;
		
		for(int index = 0; index < s.length() && index < 12; index++) {
			char c = s.charAt(index);
			hash *= 37L;
			if(c >= 'A' && c <= 'Z')
				hash += (1 + c) - 65;
			else if(c >= 'a' && c <= 'z')
				hash += (1 + c) - 97;
			else if(c >= '0' && c <= '9')
				hash += (27 + c) - 48;
		}
		while(hash % 37L == 0L && hash != 0L)
			hash /= 37L;
		return hash;
	}
	
	/**
	 * Converts a packed byte array to a String.
	 * 
	 * @param packedData
	 *            The data to convert.
	 * @param size
	 *            The size of the data.
	 * @return The converted String.
	 */
	public static String dataToString(byte packedData[], int size) {
		char[] decodeBuffer = new char[4096];
		int idx = 0, highNibble = -1;
		for(int i = 0; i < size * 2; i++) {
			int val = packedData[i / 2] >> (4 - 4 * (i % 2)) & 0xf;
			if(highNibble == -1) {
				if(val < 13) {
					decodeBuffer[idx++] = VALID_CHARACTERS[val];
				} else {
					highNibble = val;
				}
			} else {
				decodeBuffer[idx++] = VALID_CHARACTERS[((highNibble << 4) + val) - 195];
				highNibble = -1;
			}
		}
		
		return new String(decodeBuffer, 0, idx);
	}
	
	/**
	 * Changes letters in the beginning and after end markers (periods etc.) to
	 * upper case.
	 * 
	 * @param s
	 *            The string to format.
	 * @return The formatted string.
	 */
	public static String fixCase(String s) {
		char buffer[] = s.toCharArray();
		boolean endMarker = true;
		
		for(int i = 0; i < buffer.length; i++) {
			char c = buffer[i];
			if(endMarker && c >= 'a' && c <= 'z') {
				buffer[i] -= 0x20; // transform lower case into upper case
				endMarker = false;
			}
			if(c == '.' || c == '!' || c == '?') {
				endMarker = true;
			}
		}
		return new String(buffer, 0, buffer.length);
	}
	
	/**
	 * An array of valid characters recognized by the chat system.
	 */
	public final static char VALID_CHARACTERS[] = { ' ', 'e', 't', 'a', 'o', 'i', 'h', 'n', 's', 'r', 'd', 'l', 'u', 'm', 'w', 'c', 'y', 'f', 'g', 'p', 'b', 'v', 'k', 'x', 'j', 'q', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ' ', '!', '?', '.', ',', ':', ';', '(', ')', '-', '&', '*', '\\', '\'', '@', '#', '+', '=', '\243', '$', '%', '"', '[', ']' };
}
